#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# author: tangzhichao
import os
import time

import httpx
from pathlib import Path
from typing import List, Dict, Tuple, Optional, Any
from fastapi import UploadFile
from urllib.parse import quote
from datetime import datetime
from werkzeug.utils import secure_filename


class FileService:
    """文件处理服务，封装文件上传和临时文件管理"""

    def __init__(self, base_dir: str = "resource/uploads", save_type: str = "tmp"):
        self.base_dir = Path(__file__).parent.parent / base_dir
        self.base_dir.mkdir(parents=True, exist_ok=True)
        self.save_type = save_type

    async def save_upload_files(
            self,
            upload_files: List[UploadFile],
            storage_method: str = "temp"
    ) -> Tuple[Dict[str, dict], List[Path]]:
        """
        Save uploaded files with proper organization and metadata.

        Args:
            upload_files: List of files to upload
            storage_method: Storage type ('temp' or 'permanent')

        Returns:
            Tuple containing:
            - Dictionary of file metadata keyed by save path
            - List of saved file paths
        """

        saved_info = {}
        saved_paths = []
        for upload_file in upload_files:
            # 安全处理文件名
            original_name = upload_file.filename
            safe_name = secure_filename(quote(upload_file.filename))
            file_ext = os.path.splitext(original_name)[1]
            # 构建存储路径
            date_path = self._get_date_subfolder()
            save_dir = self.base_dir / storage_method / date_path
            save_dir.mkdir(parents=True, exist_ok=True)

            # 构建最终文件名
            final_name = self._generate_filename(safe_name)
            save_path = save_dir / final_name

            # 保存文件
            await self._save_file(upload_file, save_path)

            saved_info[str(save_path)] = {
                "path": str(save_path),
                "original_name": original_name,
                "final_name": final_name,
                "file_ext": file_ext
            }

            saved_paths.append(save_path)

        return saved_info, saved_paths

    async def download_and_save_multiple_remote(
            self,
            urls,
            storage_method: str = "temp"
    ) -> Tuple[Dict[str, dict], List[Path]]:
        """
        Download and save multiple remote files with metadata

        Args:
            urls: List of remote file URLs
            storage_method: Storage type ('temp' or 'permanent')

        Returns:
            Tuple containing:
            - Dictionary of file metadata keyed by save path
            - List of saved file paths

        Raises:
            ValueError: If any download fails
        """
        saved_info = {}
        saved_paths = []
        errors = []

        async with httpx.AsyncClient(timeout=60.0) as client:
            for url in urls:
                try:
                    start_time = time.time()  # 记录开始时间

                    # 1. Download file
                    download_start = time.time()
                    response = await client.get(url["url"])
                    response.raise_for_status()
                    download_duration = time.time() - download_start

                    # 2. Generate safe filename
                    original_name = url["name"] or os.path.basename(url["url"])
                    safe_name = secure_filename(quote(original_name))
                    file_ext = url["extension"]

                    # 3. Create date-based subfolder
                    date_path = self._get_date_subfolder()
                    save_dir = self.base_dir / storage_method / date_path
                    save_dir.mkdir(parents=True, exist_ok=True)

                    # 4. Create final save path
                    final_name = self._generate_filename(safe_name)
                    save_path = save_dir / final_name

                    # 5. Save file content
                    save_start = time.time()
                    with open(save_path, "wb") as buffer:
                        buffer.write(response.content)
                    save_duration = time.time() - save_start

                    # 6. Record metadata
                    total_duration = time.time() - start_time
                    saved_info[str(save_path)] = {
                        "path": str(save_path),
                        "original_name": original_name,
                        "final_name": final_name,
                        "file_ext": file_ext,
                        "source_url": url,
                        "size": os.path.getsize(save_path),
                        "saved_at": datetime.now().isoformat(),
                        "content_type": response.headers.get("content-type", "application/octet-stream"),
                        "timing": {
                            "total_seconds": total_duration,
                            "download_seconds": download_duration,
                            "save_seconds": save_duration,
                            "download_speed": f"{(len(response.content) / download_duration) / 1024:.2f} KB/s" if download_duration > 0 else "N/A"
                        }
                    }
                    print(saved_info)
                    saved_paths.append(save_path)

                except Exception as e:
                    errors.append(f"Failed to download {url}: {str(e)}")
                    continue

        if errors and not saved_paths:
            raise ValueError("\n".join(errors))
        elif errors:
            # Log partial failures but still return successful downloads
            # log_message(
            #     "partial_downloads",
            #     {"success_count": len(saved_paths), "error_count": len(errors), "errors": errors},
            #     "warning"
            # )
            pass

        return saved_info, saved_paths

    def cleanup_files(self, file_paths: List[Path]):
        """清理临时文件"""
        for path in file_paths:
            try:
                path.unlink(missing_ok=True)
            except Exception as e:
                pass
    def _get_date_subfolder(self) -> str:
        """生成年月子目录路径"""
        today = datetime.now()
        return f"{today.year}/{today.month:02d}"

    def _generate_filename(self, original_name: str) -> str:
        """生成最终文件名格式：会话名_原始文件名"""
        # if session_name:
        #     safe_session = secure_filename(session_name)
        #     return f"{safe_session}_{original_name}"
        return original_name

    async def _save_file(self, upload_file: UploadFile, save_path: Path):
        """实际保存文件"""
        with open(save_path, "wb") as buffer:
            content = await upload_file.read()
            buffer.write(content)

    @staticmethod
    def get_file_extensions(file_paths: List[Path]) -> List[str]:
        """获取文件扩展名列表"""
        return [os.path.splitext(path.name)[1].lower() for path in file_paths]